package lockDemo.semaphore;

import java.util.concurrent.Semaphore;

/**
* @author jie
* @version 创建时间：2018年7月9日 上午10:52:52
*  操场，有5个跑道
*  
*  Semaphore是计数信号量。
*  Semaphore管理一系列许可证。
*  
*  每个acquire方法阻塞，直到有一个许可证可以获得然后拿走一个许可证；
*  
*  每个release方法增加一个许可证，这可能会释放一个阻塞的acquire方法。然而，其实并没有实际的许可证这个对象，Semaphore只是维持了一个可获得许可证的数量。 
*  
*  Semaphore经常用于限制获取某种资源的线程数量。下面举个例子，比如说操场上有5个跑道，一个跑道一次只能有一个学生在上面跑步，一旦所有跑道在使用，那么后面的学生就需要等待，直到有一个学生不跑了，
*  
*/
public class Playground {
	/**
	* 跑道类
	*/
	static class Track {
		private int num;

		public Track(int num) {
			this.num = num;
		}

		@Override
		public String toString() {
			return "Track{" + "num=" + num + '}';
		}
	}

	private Track[] tracks = { new Track(1), new Track(2), new Track(3), new Track(4), new Track(5) };
	private volatile boolean[] used = new boolean[5];

	private Semaphore semaphore = new Semaphore(5, true);

	/**
	 * 获取一个跑道
	 */
	public Track getTrack() throws InterruptedException {
		System.out.println("semaphore.acquire  before");
		semaphore.acquire(1);
		System.err.println("semaphore.acquire  after");
		return getNextAvailableTrack();

	}

	/**
	 * 返回一个跑道
	 *
	 * @param track
	 */
	public void releaseTrack(Track track) {
		if (makeAsUsed(track))
			semaphore.release(1);
	}

	/**
	 * 遍历，找到一个没人用的跑道
	 *
	 * @return
	 */
	private Track getNextAvailableTrack() {

		for (int i = 0; i < used.length; i++) {
			if (!used[i]) {
				used[i] = true;
				return tracks[i];
			}
		}

		return null;

	}

	/**
	 * 返回一个跑道
	 *
	 * @param track
	 */
	private boolean makeAsUsed(Track track) {

		for (int i = 0; i < used.length; i++) {
			if (tracks[i] == track) {
				if (used[i]) {
					used[i] = false;
					return true;
				} else {
					return false;
				}

			}
		}

		return false;
	}
}
